package sunyu.tools.solr;

import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.nutz.json.Json;
import org.nutz.mapl.Mapl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class SolrTools {

    private static final Logger logger = LoggerFactory.getLogger(Thread.currentThread().getClass());
    Map<String, SolrClient> clients = new HashMap<>();
    @Value("${solr.urls}")
    private String urls;

    @PostConstruct
    public void init() {
        logger.debug(urls);
        List configs = (List) Json.fromJson(urls);
        for (Object config : configs) {
            logger.debug(Json.toJson(config));
            SolrClient client = new HttpSolrClient(Mapl.cell(config, "url") + "");
            clients.put(Mapl.cell(config, "core") + "", client);
        }
    }

    public SolrClient getClient(String core) {
        return clients.get(core);
    }

    public UpdateResponse add(String core,
                              Map<String, Object> solrInputDocumentMap) {
        List<Map<String, Object>> solrInputDocumentMapList = new ArrayList<>();
        solrInputDocumentMapList.add(solrInputDocumentMap);

        return add(core, solrInputDocumentMapList);
    }

    public UpdateResponse add(String core,
                              List<Map<String, Object>> solrInputDocumentMapList) {
        SolrClient client = getClient(core);

        List<SolrInputDocument> solrInputDocumentList = new ArrayList<>();
        for (Map<String, Object> map : solrInputDocumentMapList) {
            SolrInputDocument doc = new SolrInputDocument();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                doc.addField(entry.getKey(), entry.getValue());
            }
            solrInputDocumentList.add(doc);
        }
        try {
            UpdateResponse addResponse = client.add(solrInputDocumentList);
            logger.debug("add status:" + addResponse.getStatus());
            logger.debug("add qTime:" + addResponse.getQTime());
            UpdateResponse response = client.commit();
            logger.debug("commit status:" + response.getStatus());
            logger.debug("commit qTime:" + response.getQTime());
            return response;
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public SolrDocumentList query(String core,
                                  String q,
                                  Integer start,
                                  Integer rows,
                                  String sort,
                                  List<String> fq,
                                  String fl) {
        SolrClient client = getClient(core);

        SolrQuery params = new SolrQuery();
        if (StringUtils.isNotBlank(q)) {
            params.set("q", q);
        }
        if (start != null) {
            params.set("start", start);
        }
        if (rows != null) {
            params.set("rows", 10);
        }
        if (StringUtils.isNotBlank(sort)) {
            params.set("sort", sort);
        }
        if (fq != null) {
            SolrQuery filterQuery = new SolrQuery();
            for (String fQuery : fq) {
                filterQuery.addFilterQuery(fQuery);
            }
            params.add(filterQuery);
        }
        if (StringUtils.isNotBlank(fl)) {
            params.add("fl", fl);
        }
        try {
            QueryResponse response = client.query(params);
            SolrDocumentList documentList = response.getResults();

            logger.debug("查询内容:" + Json.toJson(params));
            logger.debug("文档数量：" + documentList.getNumFound());
            logger.debug("查询花费时间:" + response.getQTime());

            return documentList;
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public UpdateResponse deleteById(String core,
                                     String id) {
        SolrClient client = getClient(core);

        try {
            UpdateResponse deleteResponse = client.deleteById(id);
            logger.debug("delete status:" + deleteResponse.getStatus());
            logger.debug("delete qTime:" + deleteResponse.getQTime());
            UpdateResponse response = client.commit();
            logger.debug("commit status:" + response.getStatus());
            logger.debug("commit qTime:" + response.getQTime());
            return response;
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public UpdateResponse deleteByQuery(String core,
                                        String q) {
        SolrClient client = getClient(core);

        try {
            UpdateResponse deleteResponse = client.deleteByQuery(q);
            logger.debug("delete status:" + deleteResponse.getStatus());
            logger.debug("delete qTime:" + deleteResponse.getQTime());
            UpdateResponse response = client.commit();
            logger.debug("commit status:" + response.getStatus());
            logger.debug("commit qTime:" + response.getQTime());
            return response;
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
